#include "nrf24l01.h"


nrf24l01Class nrf24l01;

void nrf24l01Class::init()
{
	HAL_Delay(100);    

	while(check()==0)    //check nrf24l01
	{
		LED_TOGGLE();
		HAL_Delay(50);
	}
	memcpy(TX_ADDRESS,"12345",5);
	memcpy(RX_ADDRESS,"12345",5);
	getAddress();         //从flash中读取出来RX_ADDRESS地址
	txMode();        //两种模式配置执行一遍，对nrf24l01进行初始化
	rxMode();
	mode=MODE_RX;         //上电进入接收模式
	rxDataValid=false;    
	updataAdd=UPDATE_NONE;
}

uint8_t nrf24l01Class::writeReg(uint8_t reg,uint8_t value)
{
	uint8_t buf[2];
	uint8_t status;
	buf[0]=reg;
	buf[1]=value;
	Clr_NRF24L01_CSN;                 //使能SPI传输
	status=HAL_SPI_Transmit(&hspi1,buf,2,0xffff);
	Set_NRF24L01_CSN;                 //禁止SPI传输	
	return status;       			  //返回状态值
}
uint8_t nrf24l01Class::readReg(uint8_t reg)
{
	uint8_t reg_val;	    
	Clr_NRF24L01_CSN;          //使能SPI传输	

	HAL_SPI_Transmit(&hspi1,&reg,1,0xffff);   //发送寄存器号 
	HAL_SPI_Receive(&hspi1,&reg_val,1,0xffff);//读取寄存器内容
	
	Set_NRF24L01_CSN;          //禁止SPI传输		
	
	return(reg_val);           //返回读取数据（8位）
}
uint8_t nrf24l01Class::writeBuf(uint8_t reg,uint8_t *pBuf,uint8_t len)
{
	uint8_t status;	    
	Clr_NRF24L01_CSN;          //使能SPI传输
	status=HAL_SPI_Transmit(&hspi1,&reg,1,0xffff);//发送寄存器值
	HAL_SPI_Transmit(&hspi1,pBuf,len,0xffff);
	Set_NRF24L01_CSN;       //关闭SPI传输
	return status;          //返回读到的状态值	
}

uint8_t nrf24l01Class::readBuf(uint8_t reg,uint8_t *pBuf,uint8_t len)
{
	uint8_t status;	       
	Clr_NRF24L01_CSN;           //使能SPI传输
	status=HAL_SPI_Transmit(&hspi1,&reg,1,0xffff);//发送寄存器值(位置),并读取状态值   	   
	HAL_SPI_Receive(&hspi1,pBuf,len,0xffff);//读取寄存器内容
	Set_NRF24L01_CSN;       //关闭SPI传输
	return status;        //返回读到的状态值
}
//返回0：检测不到nrf24l01  返回1：检测OK
uint8_t nrf24l01Class::check()
{
	uint8_t buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
	uint8_t rbuf[5];
	uint8_t i;
	writeBuf(NRF24L01_WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.	
	readBuf(TX_ADDR,rbuf,5); //读出写入的地址  
	for(i=0;i<5;i++)if(rbuf[i]!=0XA5)break;	 							   
	if(i!=5)return 0;//检测24L01错误	
	return 1;		 //检测到24L01
}
uint8_t nrf24l01Class::txPacket(uint8_t *txbuf)
{
	uint8_t sta; 
	Clr_NRF24L01_CE;
	writeBuf(NRF24L01_WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF  32个字节
	Set_NRF24L01_CE;//启动发送
	delay10us(1);
	while(NRF24L01_IRQ!=GPIO_PIN_RESET);//等待发送完成
	sta=readReg(STATUS);  //读取状态寄存器的值	   
	writeReg(NRF24L01_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
	if((sta&MAX_TX)&&(sta!=0xff))//达到最大重发次数,没有插接模块的时候可能读出来是0xff
	{
		writeReg(NRF24L01_FLUSH_TX,0xff);//清除TX FIFO寄存器 
		return MAX_TX; 
	}
	if((sta&TX_OK)&&(sta!=0xff))//发送完成,没有插接模块的时候可能读出来是0xff
	{
		return TX_OK;
	}
	return 0xff;//其他原因发送失败
}
uint8_t nrf24l01Class::rxPacket(uint8_t *rxbuf)
{
	uint8_t sta;		    							   
	sta=readReg(STATUS);  //读取状态寄存器的值    	 
	writeReg(NRF24L01_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
	if((sta&RX_OK)&&(sta!=0xff))//接收到数据,没有插接模块的时候可能读出来是0xff
	{
		readBuf(NRF24L01_RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
		writeReg(NRF24L01_FLUSH_RX,0xff);//清除RX FIFO寄存器 
		return 1; 
	}	   
	return 0;//没收到任何数据
}

void nrf24l01Class::txMode()
{
	Clr_NRF24L01_CE;	    
	writeBuf(NRF24L01_WRITE_REG+TX_ADDR,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址 
	writeBuf(NRF24L01_WRITE_REG+RX_ADDR_P0,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK	  
	
	writeReg(NRF24L01_WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答    
	writeReg(NRF24L01_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
	writeReg(NRF24L01_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
	writeReg(NRF24L01_WRITE_REG+RF_CH,40);       //设置RF通道为40
	writeReg(NRF24L01_WRITE_REG+RF_SETUP,0x0f);  //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
	writeReg(NRF24L01_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
	Set_NRF24L01_CE;
}
void nrf24l01Class::rxMode()
{
	Clr_NRF24L01_CE;	  
	writeBuf(NRF24L01_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址
	writeReg(NRF24L01_WRITE_REG+EN_AA,0x01);    //使能通道0的自动应答    
	writeReg(NRF24L01_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址  	 
	writeReg(NRF24L01_WRITE_REG+RF_CH,40);	     //设置RF通信频率		  
	writeReg(NRF24L01_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度 	    
	writeReg(NRF24L01_WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
	writeReg(NRF24L01_WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式 
	Set_NRF24L01_CE; //CE为高,进入接收模式 	
}




void nrf24l01Class::quickTxMode()
{
	Clr_NRF24L01_CE;
	writeBuf(NRF24L01_WRITE_REG+TX_ADDR,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址 
	writeBuf(NRF24L01_WRITE_REG+RX_ADDR_P0,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH); //设置RX节点地址,主要为了使能ACK	   
	writeReg(NRF24L01_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
	Set_NRF24L01_CE; //CE为高,进入接收模式 
}
void nrf24l01Class::quickRxMode()
{
	Clr_NRF24L01_CE;	  
//	writeBuf(NRF24L01_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址  
	writeReg(NRF24L01_WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式 
	Set_NRF24L01_CE; //CE为高,进入接收模式 
}

uint8_t nrf24l01Class::scanTx()
{
	uint8_t sta;
	if(mode!=MODE_TX) return 0;
	quickTxMode();
	sta=txPacket(txBuf);
	quickRxMode();
	mode=MODE_RX;
	return sta;
}

uint8_t nrf24l01Class::scanRx()
{
	uint8_t sta;
	if(mode!=MODE_RX||NRF24L01_IRQ!=GPIO_PIN_RESET)return 0;
	sta=rxPacket(rxBuf);
	if(sta==1)
	{
		memcpy(rxBufCache,rxBuf,RX_PLOAD_WIDTH);    //把接受到的数据放入缓冲区，避免i2c命令和接收同时操作rxBuf
		rxDataValid=true;		
	}
	
	
	return sta;	
}
uint8_t nrf24l01Class::scanUpdateAdd()
{
	if(updataAdd==UPDATE_NONE)return 0;
	else if(updataAdd==UPDATA_TXADD)
	{
		Clr_NRF24L01_CE;
		writeBuf(NRF24L01_WRITE_REG+TX_ADDR,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址 
		writeBuf(NRF24L01_WRITE_REG+RX_ADDR_P0,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
		Set_NRF24L01_CE; //CE为高,进入接收模式
		updataAdd=UPDATE_NONE;
	}
	else if(updataAdd==UPDATA_RXADD)
	{
		Clr_NRF24L01_CE;
		writeBuf(NRF24L01_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址
		Set_NRF24L01_CE; //CE为高,进入接收模式
		updataAdd=UPDATE_NONE;
		saveAddress();  //把RX_ADDRESS保存进flash
	}
	return 1;
}

void nrf24l01Class::setTxAdd(uint8_t *add)
{
	updataAdd=UPDATA_TXADD;
	memcpy(TX_ADDRESS,add,TX_ADR_WIDTH);		
}
void nrf24l01Class::setRxAdd(uint8_t *add)
{
	updataAdd=UPDATA_RXADD;
	memcpy(RX_ADDRESS,add,RX_ADR_WIDTH);
}
void nrf24l01Class::setTxData(uint8_t *add,uint8_t len,uint8_t *txdat)
{
	if(len>TX_PLOAD_WIDTH)len=TX_PLOAD_WIDTH;
	memcpy(TX_ADDRESS,add,TX_ADR_WIDTH);
	memcpy(txBuf,txdat,len);
	mode=MODE_TX;	
	rxDataValid=false;     //每次发送的时候就把之前接收到的清楚
}
void nrf24l01Class::setTxData(uint8_t len,uint8_t *txdat)
{
	if(len>TX_PLOAD_WIDTH)len=TX_PLOAD_WIDTH;
	memcpy(txBuf,txdat,len);
	mode=MODE_TX;
	rxDataValid=false;     //每次发送的时候就把之前接收到的清楚
}
uint8_t nrf24l01Class::getRxState()
{
	if(rxDataValid)return 1;
	else return 0;
}
uint8_t nrf24l01Class::getRxData(uint8_t len,uint8_t *buf)
{
	if(rxDataValid==false)return 0;
	if(len>RX_PLOAD_WIDTH)len=RX_PLOAD_WIDTH;
	memcpy(buf,rxBufCache,len);    //读取缓冲区里面的数据
	rxDataValid=false;
	return 1;
}
//把RX_ADDRESS保存进flash
void nrf24l01Class::saveAddress()
{
	uint8_t i;
	uint32_t PageError = 0;
	static FLASH_EraseInitTypeDef EraseInitStruct;
		
	HAL_FLASH_Unlock();
	EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
  EraseInitStruct.PageAddress = RXADD_FLASH_PAGE;
  EraseInitStruct.NbPages = 1;  //Number of pagess to be erased.
	
	HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
	for(i=0;i<RX_ADR_WIDTH;i++)
	{
			HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, RXADD_FLASH_PAGE+i*4,RX_ADDRESS[i]);
	}	
	HAL_FLASH_Lock();
}
//从flash中读取RX_ADDRESS
void nrf24l01Class::getAddress()
{
	uint8_t i;
	
	for(i=0;i<RX_ADR_WIDTH;i++)
	{
			*(RX_ADDRESS+i) = *(__IO uint32_t*)(RXADD_FLASH_PAGE+i*4);
	}
}

